/* 
 *  Copyright (C) 2007 Dip. Ing. dell'Informazione, University of Pisa, Italy
 *  http://info.iet.unipi.it/~cng/ns2mesh80216/
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA, USA
 */

#ifndef __NS2_MESH_PHY_H
#define __NS2_MESH_PHY_H

#include "w_mesh_common.h"
#include <t_timers.h>

#include <packet.h>
#include <wireless-phy.h>
#include "w_mesh_defs.h"

#include <list>

class MeshChannel;
class MeshBurst;
class MeshMac;
class MeshTopologySimple;

/*物理层支持的调制方式*/// 已经计算了着空编码后的码率了，参照协议table－215
// 在w_mesh_def.h 中 BurstProfile 有定义；

//enum Ofdm_mod_rate {
//OFDM_BPSK_1_2=0, /* Efficiency is 1 bps/Hz *///星座图的一点含有1比特数据量
//OFDM_QPSK_1_2=0,   /* Efficiency is 2 bps/Hz *///星座图的一点含有2比特数据量
//OFDM_QPSK_3_4,   /* Efficiency is 2 bps/Hz */
//OFDM_16QAM_1_2,  /* Efficiency is 4 bps/Hz *///星座图的一点含有4比特数据量
//OFDM_16QAM_3_4,  /* Efficiency is 4 bps/Hz */
//OFDM_64QAM_2_3,  /* Efficiency is 6 bps/Hz *///星座图的一点含有6比特数据量
//OFDM_64QAM_3_4,  /* Efficiency is 6 bps/Hz */
//};


/**
 * 计算每个ofdm符号所含有的字节数（有用的)，即没有调制之前的字节数
 * 每个ofdm有256个子载波，其中可用子载波数为200，有8个用于导频，
 * 每个ofdm符号共有192个数据子载波
 * 码率为 (1/2, 2/3, or 3/4)
 * There is a 0x00 tail byte at the end of each OFDM symbol	？？？？？？？？
 * So for BPSK, 192*1*1/2-8=88
与 alpha[6]对应；
   */
/*enum Ofdm_bytes_per_symbol {
  OFDM_BPSK_1_2_bytes = 12,   mesh不支持
  OFDM_QPSK_1_2_bytes = 24,   alpha[0]
  OFDM_QPSK_3_4_bytes = 36,   
  OFDM_16QAM_1_2_bytes = 48,  
  OFDM_16QAM_3_4_bytes = 72,  
  OFDM_64QAM_2_3_bytes = 96,  
  OFDM_64QAM_3_4_bytes = 108,  alpha[6]
};*/



//! Physical layer management information base.
class MeshPhyMib : public TclObject {

public:
	//! Uncoded block size (in bytes) for each burst profile.
	static const unsigned int alpha[6];


private:

	//! OFDM symbol duration (in second). 根据调制方式，带宽等计算的，初始化时求出；
	double symDuration_;	
	//! Frame duration (in seconds). Set via Tcl command.	绑定
	// 16 的帧长度有明确的规定！！！！！！！
	double frameDuration_;
	//! Number of OFDM symbols per frame.	recompute中求
	unsigned int symPerFrame_;
	//! Number of control slots per frame.			#绑定
	unsigned int controlSlots_;
	//! Number of minislots per frame.	MeshPhyMib::recompute ()
	unsigned int slotPerFrame_;
	//! Number of OFDM symbols per minislot. 在MeshPhyMib::recompute ()
	unsigned int symPerSlot_;
	//! Number of scheduling frames between two consecutive configuration ones. #绑定
	unsigned int cfgInterval_;
	//当前的调制方式			 			#绑定
	w_mesh::BurstProfile modulation_;
	//频带宽度			 			#绑定
	double fbandwidth_;
	//采样频率			初始化的时候求出；	M单位；
	double fs_;
	//Ratio of CP time over useful time			#绑定
	double g_;

public:
	//! Build an empty PHY.
	MeshPhyMib ();
	//! Do nothing.
	virtual ~MeshPhyMib () { }

	// 跟新采样频率，在mib初始化是调用；
	//void UpdateFs (double& fs_);

	// update symduration_ 初始化时调用
	void UpsymDuration (); 

	//! Tcl interface.
	virtual int command(int argc, const char*const* argv);

	//! Return the frame duration (in seconds).
	double frameDuration () { return frameDuration_ ; }

	//! Return the OFDM symbol duration (in seconds).
	double  symDuration () { return symDuration_; }
	
	//! Return the data slot duration.
	double slotDuration () { return symPerSlot_ * symDuration_; }
	//! Return the control slot duration.
	double controlSlotDuration () { return 7 * symDuration_; }

	//! Return the start time of the next frame (in seconds).
	double nextFrame ();

	//! Return the number of OFDM symbols per frame.
	unsigned int  symPerFrame () { return symPerFrame_; }
	//! Return the number of OFDM symbols per minislot.
	unsigned int  symPerSlot () { return symPerSlot_; }
	//! Return the number of minislots per frame.
	unsigned int slotPerFrame () { return slotPerFrame_; }
	//! Return the number of control slots per frame.
	unsigned int controlSlots () { return controlSlots_; }
	//! Return the configuration frames interval.
	unsigned int cfgInterval () { return cfgInterval_; }

	//! Return the number of OFDM symbols of a short preamble, for data PDUs.
	unsigned int symShortPreamble () { return 1; }
	//! Return the number of OFDM symbols of a long preamble, for control PDUs.
	unsigned int symLongPreamble () { return 2; }

	//! Return the duration of the control subframe (in seconds).
	double controlDuration () { return controlSlotDuration() * controlSlots(); }
	//! Return the duration of the data subframe (in seconds).
	/*!
	  Note that this is not product of the minislot duration times the
	  number of minislots. It is the difference between the frame duration
	  and the control subframe duration.
	  */
	double dataDuration () { return frameDuration_ - controlDuration(); }

	double GetTrxTime (int, w_mesh::BurstProfile);//计算给定的调制方式下发送给定长sdu所需的时间

  	void  SetModulation (w_mesh::BurstProfile modulation);//设置调制方式    

  	w_mesh::BurstProfile GetModulation ();//获取物理层的调制方式

protected:
	//! Recompute derived parameters. 只是用于判断取值是否正确；不是用于计算;
	bool recompute ();

	//! Dump the parameters to the specified output stream.
	//  void dump (FILE* os);
};

//! Physical layer.
class MeshPhy : public WirelessPhy {

friend class ActiveNeighborTimer;

protected:
	//! Descriptor for each received burst, to detect inteference.

// 这个类不要了，但需要在packet中添加相应的标志位；
/*	struct BurstDesc {
		//! Source node.
		W_MeshNodeId src_;
		//! Destination node.
		W_MeshNodeId dst_;
		//! Tx start time.
		double start_;
		//! Tx finish time.
		double finish_;
		//! Pointer to the channel over which this burst was received.
		MeshChannel* channel_;
		//! Burst dispatched (neighbor only, otherwise null).;
		MeshBurst* burst_;
	};*/

	//! List of descriptors of received bursts to detect interference.
//	std::list<BurstDesc> rxBursts_;

struct recvPacket {

	Packet* pkt_;
	double start_;
	double finish_;
	
};

//! List of  received Packet to detect interference.
	std::list<recvPacket> rxPacket_;

	//! Multi-timer for transmission finish times.  
	TMultiTimer<MeshPhy, Packet* > rxFinishTimes_;

	//! Pointer to the channel to which the PHY is connected (either tx/rx).
	MeshChannel* channel_;

	//! Pointer to the PHY MIB.
	//MeshPhyMib* phyMib_;

	//! Pointer to the MAC layer.
	//MeshMac* mac_;

	//! Pointer to the topology. 不存在了
//	MeshTopologySimple* topology_;
	

	//! Small amount of time that is used to check for transmission collision.
	/*!
	  This value should definitely be smaller than the duration of an
	  OFDM symbol.
	  */
	double epsilon_;





public:
	//! Initialize an empty PHY.
	MeshPhy ();
	//! Do nothing.
	virtual ~MeshPhy () { }

	//! Switch the channel/mode used by this PHY.
	/*!
	  If no channel is specified, then only the mode is changed.
	  If there is a channel switch or a tx/rx switch, then
	  we drop any burst which has not been dispatched yet.

	  :TODO: This function should be optimized.	有待修改，对应channel
	  */
	//void setMode (w_mesh::ChannelStatus s, MeshChannel* channel = 0);
	//! Send a burst to the current channel.
	/*!
	  Compute the burst duration (including physical preamble, if needed)
	  and send the latter to the channel.
	  */
	void sendBurst (MeshBurst* burst);
	//! Receive a burst from the channel (perhaps corrupted).
	/*!
	  Drop any corrupted PDU and then pass the PDUs to the MAC layer.
	  */
	//void recvBurst (MeshBurst* burst);
	//! Handle the timer_ event.
	/*!
	  Get the burst with the earliest finish time. If this is from a
	  neighbor of ours, then check whether there are ongoing communications
	  which interfere with this one. If so, then set the error flag
	  into the burst. In any case, pass the burst to the MAC layer.
	  If this is not from a neighbor of ours, then just ignore the burst.
	  The burst is also ignore if there was a channel or tx/rx switch
	  of the PHY during this burst's transmission.
	  
	  :TODO: This function should be optimized.	
	  */ 
	void handle (Packet* p);

	
	void recv(Packet* p, Handler*);

protected:
	//! Tcl interface.
	virtual int command(int argc, const char*const* argv);
	
	/* Overwritten methods for handling packets */// 重载了下面两个函数
  	void sendDown(Packet *p);
  
  	int sendUp(Packet *p);
	


private:
	//! Utility function to determine whether transmissions overlap.
	/*!
	  Return true if x is greater than y of at most one epsilon_.
	  */
	bool gt (double x, double y) {
		return ( x > ( y + epsilon_ ) ) ? true : false; }

	W_MeshNodeId nodeId_;


private:
	MeshPhy (const MeshPhy&);
	void operator= (const MeshPhy&);

};

#endif // __NS2_MESH_PHY_H
